#pragma once
#include <signal.h>
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/types.h> 
#include <arpa/inet.h>
#include <netinet/in.h>
#include <jsoncpp/json.h>
#include <memory>
#include <string>
#include <set>
#include <functional>
#include "socket.hpp"
#include "thread_pool.hpp"
#include "Prorocol.hpp"
#include "log.hpp"


namespace tr
{

// 成为守护进程
void daemon()
{
    // 在Unix系统下，如果recv函数在等待协议接收数据时网络断开了，
    // 那么调用recv的进程会接收到一个SIGPIPE信号，进程对该信号的默认处理是进程终止。
    // 1. 忽略异常信号，保证守护进程不轻易退出
    signal(SIGPIPE,SIG_IGN);
    signal(SIGCHLD,SIG_IGN);
    // .... 按照需求忽略其他信号

    // 2. fork 创建子进程
    if(fork() > 0) exit(0); // 退出父进程，子进程变为孤儿进程

    // 3. 创建新会话
    setsid();

    // 4. 按照需求切换守护进程工作目录
    // chdir("/");

    // 5. 处理 stdin、stdout、stderr
    // 使用 /dev/null，向该文件写入的所有数据都会被丢弃
    // 也可以直接关闭三个输入输出流，看项目需求
    int fd = open("/dev/null",O_RDWR);
    dup2(fd,0);
    dup2(fd,1);
    dup2(fd,2);
}


class tcp_serve
{
    using sock_ptr = std::shared_ptr<tcp_socket>;
    tcp_socket _m_addr;
    std::set<sock_ptr> _m_users;    // 维护在线用户
public:
    tcp_serve(uint16_t port)
        :_m_addr(port,INADDR_ANY)
    {
        // 获取线程池
        if(_m_addr.bind() or _m_addr.listen()) exit(0);
        log(INFO) << "TCP Service initialization successful." << std::endl;
    }

    // 接收用户，只有一个线程执行该任务，所以不用考虑线程安全
    void accept_user()
    {
        for(;;)
        {
            sock_ptr _new_user = _m_addr.accept();
            if(_new_user == nullptr)continue;

            // 为连接用户提供服务
            std::function<void(tcp_serve*,sock_ptr)> f = &tcp_serve::serve;
            
            thread_pool::get_pool()->add_task(f,this,_new_user);

            log(INFO) << "New user [IP:" << _new_user->get_ip() 
                << ",Port:" << _new_user->get_port() 
                << "] has been joined." << std::endl;
                
            _m_users.insert(_new_user);
        }
    }

    // 为用户提供服务
    void serve(sock_ptr _user)
    {
        for(;;)
        {
            Json::Value msg;
            int ret = _user->recv(msg);
            if(ret <= 0)
            {
                _m_users.erase(_user);
                log(INFO) << "Delete user" << "[IP:" << _user->get_ip() 
                    << ",Port:" << _user->get_port() 
                    << "]" << std::endl;
                return;
            }
            // log(INFO) << "Recv info from" << "[IP:" << _user->get_ip() 
            //     << ",Port:" << _user->get_port() 
            //     << "] #" << Json::FastWriter().write(msg) << std::endl;
            
            // 成功接收数据
            // 将消息转发给其他用户
            std::string _to_other_msg = msg["msg"].asString();
            _to_other_msg = _user->addr_info() + "#" + _to_other_msg;
            msg["msg"] = _to_other_msg;
            for(auto& user:_m_users)
            {
                std::function<int(tcp_socket*,const Json::Value&)> 
                    f = &tcp_socket::send;
                thread_pool::get_pool()->add_task(f,user.get(),msg);
            }
        }
    }



    // 启动 talk room 服务 
    void start()
    {
        // 启动线程池
        thread_pool::get_pool()->start();
        // 开始接收用户
        
        std::function<void(tcp_serve*)> f = &tcp_serve::accept_user;
        thread_pool::get_pool()->add_task(f,this);

        log(INFO) << "Begin server in [IP:"<< _m_addr.get_ip() <<",Port:"<< 
         _m_addr.get_port()<<"]" << std::endl;
    }
};

} // end of tr